<?php

declare(strict_types=1);

namespace app\service;

use app\model\User;
use app\validate\LoginValidate;
use think\Exception;
use think\exception\ValidateException;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;

/**
 * 用户登录服务类
 *
 * 处理业务逻辑，执行操作，包括数据验证、用户创建、验证码处理等。
 */
class LoginService
{
    /**
     * 用户登录
     * @param array $data 登录表单数据
     * @return array 登录结果数组 ['success' => bool, 'message' => string, 'data' => [user info]]
     */
    public function login(array $data): array
    {
        try {
            // 1. 数据验证
            $this->validateInputData($data);

            // 2. 执行业务逻辑 - 验证用户身份
            $user = $this->authenticateUser($data);

            return [
                'success' => true,
                'message' => '登录成功',
                'data'    => [
                    'user_id'  => $user->id,
                    'username' => $user->username,
                    'email'    => $user->email,
                    // 可以添加其他需要缓存的用户信息
                ],
            ];
        } catch (ValidateException $e) {
            return [
                'success' => false,
                'message' => $e->getError(),
            ];
        } catch (DataNotFoundException | ModelNotFoundException $e) {
            return [
                'success' => false,
                'message' => '用户名或密码错误。',
            ];
        } catch (Exception $e) {
            return [
                'success' => false,
                'message' => '登录过程中发生未知错误，请稍后再试。',
            ];
        }
    }

    /**
     * 数据验证
     *
     * 使用 UserValidate 验证器的 'login' 场景来校验输入数据。
     *
     * @param array $data 待验证的数据
     * @return void 验证通过则无返回，验证失败则抛出 ValidateException
     * @throws ValidateException 验证失败时抛出
     */
    protected function validateInputData(array $data): void
    {
        // 检查验证码
        $inputCaptcha = $data['captcha'] ?? '';
        if (!captcha_check($inputCaptcha)) {
            throw new ValidateException('验证码错误');
        }

        // 验证表单数据
        validate(LoginValidate::class)->check($data);
    }

    /**
     * 验证用户身份
     *
     * 根据用户名/邮箱和密码查找并验证用户。
     *
     * @param array $data 已验证的登录数据，应包含 username (可能是用户名或邮箱) 和 password
     * @return User 验证成功的用户模型实例
     * @throws DataNotFoundException  如果用户不存在
     * @throws ModelNotFoundException 如果用户不存在 (取决于模型查询方式)
     * @throws Exception              如果密码验证失败或其他错误
     */
    protected function authenticateUser(array $data): User
    {
        $identifier = $data['username'];
        $password   = $data['password'];

        // 根据标识符（用户名或邮箱）查找用户
        $user = User::where(function ($query) use ($identifier) {
                $query->where('username', $identifier)
                      ->whereOr('email', $identifier);
        })->find();

        // 如果没找到用户
        if (!$user) {
            throw new DataNotFoundException('用户不存在', 'User');
        }

        // 验证密码
        if (!$user->checkPassword($password)) {
            throw new DataNotFoundException('用户名或密码错误。', 'User');
        }

        return $user;
    }
}
